package com.foreveross.weixin.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;  
import java.util.ArrayList;
import java.util.Arrays;  
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import com.foreveross.weixin.common.Constant;
import com.foreveross.weixin.vo.SignVo;
  
/** 
 * 请求校验工具类 
 *  
 * @author wangming 
 * @date 2013-05-18 
 */  
public class SignUtil  {  
    
  
    /** 
     * 验证签名 
     *  
     * @param signature 
     * @param timestamp 
     * @param nonce 
     * @return 
     */  
    public static boolean checkSignature(String signature, String timestamp, String nonce) {  
        String[] arr = new String[] { Constant.TOKEN, timestamp, nonce };  
        // 将token、timestamp、nonce三个参数进行字典序排序  
        Arrays.sort(arr);  
        StringBuilder content = new StringBuilder();  
        for (int i = 0; i < arr.length; i++) {  
            content.append(arr[i]);  
        }  
        MessageDigest md = null;  
        String tmpStr = null;  
  
        try {  
            md = MessageDigest.getInstance("SHA-1");  
            // 将三个参数字符串拼接成一个字符串进行sha1加密  
            byte[] digest = md.digest(content.toString().getBytes());  
            tmpStr = byteToStr(digest);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  
  
        content = null;  
        // 将sha1加密后的字符串可与signature对比，标识该请求来源于微信  
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;  
    }  
    
    /**
     * JS-SDK 验证配置
     * @param jsapi_ticket
     * @param url
     * @return
     */
    public static SignVo sign(String jsapi_ticket, String url) {
    	SignVo signVo = new SignVo();
        String nonce_str = StringUtil.create_nonce_str();
        String timestamp = StringUtil.create_timestamp();
        String string1;
        String signature = "";
        if(url != null && !"".equals(url) )
        	//注意这里参数名必须全部小写，且必须有序
            
	        string1 = "jsapi_ticket=" + jsapi_ticket +
			                "&noncestr=" + nonce_str +
			                "&timestamp=" + timestamp +
			                "&url=" + url;
        else
        	//注意这里参数名必须全部小写，且必须有序
        	string1 = "jsapi_ticket=" + jsapi_ticket +
				            "&noncestr=" + nonce_str +
				            "&timestamp=" + timestamp;
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToStr(crypt.digest());
        }catch (NoSuchAlgorithmException e){
            e.printStackTrace();
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        
        signVo.setUrl(url);
        signVo.setAppId(Constant.appId);
        signVo.setJsapi_ticket(jsapi_ticket);
        signVo.setNonceStr(nonce_str);
        signVo.setTimestamp(timestamp);
        signVo.setSignature(signature);

        return signVo;
    }
    
    
    /**
     * 获取支付所需签名
     * 
     * @throws Exception
     */
    public static String getPayCustomSign(Map bizObj,String key) throws Exception {
         
        String bizString = FormatBizQueryParaMap(bizObj,
                false);
        return payCustomSign(bizString, key);
    }
    
    
    /** 
     * 将字节数组转换为十六进制字符串 
     *  
     * @param byteArray 
     * @return 
     */  
    private static String byteToStr(byte[] byteArray) {  
        String strDigest = "";  
        for (int i = 0; i < byteArray.length; i++) {  
            strDigest += byteToHexStr(byteArray[i]);  
        }  
        return strDigest;  
    }  
  
    
	private static String FormatBizQueryParaMap(Map paraMap,
            boolean urlencode) throws Exception {
 
        String buff = "";
        try {
           
			List<Entry> infoIds = new ArrayList<Entry>(
                    paraMap.entrySet());
 
            Collections.sort(infoIds,
                    new Comparator() {
						@Override
						public int compare(Object o1, Object o2) {
							return (((Entry) o1).getKey()).toString().compareTo(
                                    (String) ((Entry) o2).getKey());
						}
                    });
 
            for (int i = 0; i < infoIds.size(); i++) {
                Map.Entry item = infoIds.get(i);
                //System.out.println(item.getKey());
                if (item.getKey() != "") {
                     
                    String key = (String) item.getKey();
                    String val = (String) item.getValue();
                    if (urlencode) {
                        val = URLEncoder.encode(val, "utf-8");
 
                    }
                    buff += key + "=" + val + "&";
 
                }
            }
 
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return buff;
    }
    
    
	private static String payCustomSign(String content, String key)
            throws Exception{
        String signStr = "";
        signStr = content + "&key=" + key;
        return MD5Util.MD5Encryption(signStr).toUpperCase();
    }
    
    /** 
     * 将字节转换为十六进制字符串 
     *  
     * @param mByte 
     * @return 
     */  
    private static String byteToHexStr(byte mByte) {  
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  
        char[] tempArr = new char[2];  
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];  
        tempArr[1] = Digit[mByte & 0X0F];  
  
        String s = new String(tempArr);  
        return s;  
    } 
    

}  
